import { Vue } from "./install.js";
import { forEach } from "./utils.js";
import ModuleCollection from "./module-collection.js";

function installModule(store, rootState, path, module) {
  // a/b/c/d
  // 获取moduleCollection类的实例
  let ns = store._modules.getNamespaced(path);
  console.log(rootState);
  // module.state => 放到rootState对应的儿子里
  if (path.length > 0) {
    // 这是一个儿子模块
    // 需要找到对应的父模块， 将状态声明上去
    // {name: 'zf', age: '12', a: aState}
    let parent = path.slice(0, -1).reduce((memo, current) => {
      return memo[current];
    }, rootState);
    // 对象新增属性不能导致重新更新视图
    Vue.set(parent, path[path.length - 1], module.state);
  }
  // 需要循环当前模块的
  // module._raw.getters 不符合规范
  module.forEachGetter((fn, key) => {
    // console.log(fn, key);
    store.wrapperGetters[ns + key] = function () {
      return fn.call(store, module.state);
    };
  });
  module.forEachMutation((fn, key) => {
    // console.log(fn, key);
    store.mutations[ns + key] = store.mutations[ns + key] || [];
    store.mutations[ns + key].push((payload) => {
      return fn.call(store, module.state, payload);
    });
  });
  module.forEachAction((fn, key) => {
    // console.log(fn, key);
    store.actions[ns + key] = store.actions[ns + key] || [];
    store.actions[ns + key].push((payload) => {
      return fn.call(store, store, payload);
    });
  });
  module.forEachChildren((child, key) => {
    installModule(store, rootState, path.concat(key), child);
  });
}

class Store {
  constructor(options) {
    // 对用户的模块进行整合
    this._modules = new ModuleCollection(options);
    // 对用户的参数进行树状格式化操作
    // console.log(this.modules, "****");
    this.wrapperGetters = {};
    this.getters = {};
    this.mutations = {};
    this.actions = {};
    // 我需要将模块中的所有的getters、mutations、actions进行封装
    // 没有namespace的时候， getters都放在根上，actions、mutations会被合并数组
    const computed = {};
    // Object.defineProperty()

    // 需要知道父子关系
    let state = options.state;
    installModule(this, state, [], this._modules.root);
    // console.log(this.getters, this.mutations, this.actions);

    forEach(this.wrapperGetters, (getter, key) => {
      computed[key] = getter;
      Object.defineProperty(this.getters, key, {
        get: () => {
          return this._vm[key];
        },
      });
    });
    this._vm = new Vue({
      data: {
        $$state: state,
      },
      computed: computed,
    });
  }
  get state() {
    return this._vm._data.$$state;
  }

  commit = (mutationName, payload) => {
    // 发布
    this.mutations[mutationName] &&
      this.mutations[mutationName].forEach((fn) => fn(payload));
  };

  dispatch = (actionName, payload) => {
    this.actions[actionName] &&
      this.actions[actionName].forEach((fn) => fn(payload));
  };
}

// state, getters, mutations, actions(modules分层)
export default Store;
